package com.vcc.web.core.interceptor;


import cn.dev33.satoken.annotation.SaCheckLogin;
import com.alibaba.fastjson2.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.vcc.core.exception.ProgramException;
import com.vcc.core.exception.SignInException;
import com.vcc.core.util.IpUtil;
import com.vcc.data.entity.User;
import com.vcc.data.entity.WhiteLabel;
import com.vcc.service.service.IpInfoService;
import com.vcc.service.service.UserService;
import com.vcc.service.service.WhiteLabelService;
import com.vcc.web.core.config.AccountConfig;
import com.vcc.web.core.util.UserUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Log4j2
@Component
public class AuthInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);

    @Autowired
    private UserService userService;

    @Autowired
    private AccountConfig accountConfig;
    @Autowired
    private IpInfoService ipInfoService;
    @Resource
    private WhiteLabelService whiteLabelService;
    @Value("${spring.profiles.active}")
    private String activeProfile;

    private static final Cache<String, JSONObject> whiteLabelCache = Caffeine.newBuilder()
            .maximumSize(10000)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();


    @Override()
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }
        log.info("请求路径: {}, 请求方法: {}, 请求IP: {}",
                request.getRequestURI(),
                request.getMethod(),
                IpUtil.getIp(request));
        String source = request.getHeader("source");
        String host = request.getHeader("host");
        System.out.println("source = " + source);
        System.out.println("host = " + host);
        if (activeProfile.equals("prod") && !source.equals("www.allwincard.com")) {
            //正式环境下判断域名是否绑定
            JSONObject temp = whiteLabelCache.get(source, key -> {
                Boolean exists = whiteLabelService.existsByDomain(source);
                if (!exists) {
                    return JSONObject.of(
                            "exists", false
                    );
                }
                WhiteLabel whiteLabel = whiteLabelService.getByDomain(source);
                return JSONObject.of(
                        "exists", true,
                        "status", whiteLabel.getStatus()
                );
            });

            if (!temp.getBoolean("exists")) {
                throw new ProgramException("当前域名未绑定，请联系管理员");
            }
            if (temp.getInteger("status") == null || temp.getInteger("status") != 0) {
                throw new ProgramException("当前域名状态异常，请联系管理员");
            }
        }
        try {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            SaCheckLogin userAuthenticate = method.getAnnotation(SaCheckLogin.class);
            //如果没有加注解则userAuthenticate为null
            if (Objects.nonNull(userAuthenticate)) {
                User user = UserUtil.get();
                //判断访问host的父级Id是不是当前用户的父级id
                Integer status = userService.getStatusById(user.getId());
                if (user.getParentId() != null && user.getParentId() > 0) {
                    // 如果有父级用户，则检查父级用户状态
                    Integer parentStatus = userService.getStatusById(user.getParentId());
                    if (parentStatus == null || !parentStatus.equals(0)) {
                        logger.info("用户ID: {}, 父级用户ID: {}, 状态: {},账号状态异常，提出登录", user.getId(), user.getParentId(), parentStatus);
                        userService.updateStatusById(user.getId(), parentStatus);
                        throw new SignInException("主账户状态异常，请联系管理员");
                    }
                }
                logger.info("用户ID: {}, 状态: {}", user.getId(), status);
                if (status == null || status < 0) {
                    logger.info("用户ID: {}, 状态: {},账号状态异常，提出登录", user.getId(), status);
                    throw new SignInException("请重新登录");
                }
                // 0 可用 1 禁用  2  管理员禁用 3  注销
                if (status == 1) {
                    logger.info("用户ID: {}, 状态: {},账号状态禁用，提出登录", user.getId(), status);
                    throw new SignInException("账号已被禁用");
                }
                if (status == 2) {
                    logger.info("用户ID: {}, 状态: {},账号状态风控冻结，提出登录", user.getId(), status);
                    throw new SignInException("账号已被风控冻结");
                }
                if (status == 3) {
                    logger.info("用户ID: {}, 状态: {},账号状态注销，提出登录", user.getId(), status);
                    throw new SignInException("账号已注销");
                }
                if (status == 4) {
                    logger.info("用户ID: {}, 状态: {},账号状态未激活，提出登录", user.getId(), status);
                    throw new SignInException("账号尚未激活无法使用");
                }
            }
            return true;
        } catch (Exception e) {
            logger.error("报错", e);
            throw e instanceof SignInException ? e : new SignInException("请重新登录");
        }
    }
}
